#include "eval.h"

void eval::InfixToPostfix(string str)
{
	Stack stack;
	int from;

	int str_length = str.length();

	for(int i=0; i < str_length; i++)
	{
		if( str[i] >= '0' && str[i] <= '9') //if number
		{
			from = i++;
			while( str[i] >= '0' && str[i] <= '9')
				i++;
			m_num_stack.Push(StrToInt(str.substr(from,(i-from))));		//send to function that return an int --> insert to num_stack
			m_op_stack.Push('#');
			i--;
		}
		else if(str[i] == ' ')
			continue;
		else //op is operator or parenthesis
		{
			while( !(stack.isEmpty()) && ( StackPriority(stack.Top()) >= InputPriority(str[i]) ) )
				m_op_stack.Push( stack.Pop());
			if( str[i] != ')' ) 
				stack.Push(str[i]);
			else
				stack.Pop();
		}
	}
	while( !stack.isEmpty() )
		m_op_stack.Push(stack.Pop());
}

int eval::StackPriority( ItemType op)
{
	switch(op)
	{
		case '+':
		case'-':  return 1;
		case '*': 
		case '/': return 2;
		case '(': return -1;
		default:  return 0;
	}
}

int eval::InputPriority( ItemType op)
{
	switch(op)
	{
		case '+':
		case'-':  return 1;
		case '*': 
		case '/': return 2;
		case '(': return 3;
		case ')': return 0;
		default:  return 0;
	}
}

int eval::StrToInt(string str)
{
	int num=0, length = str.length();
	
	for(int i=0; i < length; i++)
		num +=  (str[length-i-1] - TO_INT) * pow(10,i);

	return num;
}

int eval::Compute(char op,int num2, int num1)
{
	switch(op)
	{
		case '+':	return num1 + num2;
		case '-':	return num1 - num2;
		case '*':	return num1 * num2;
		case '/':	if(num2 == 0)
					{
						cout << "The expression is not valid"<<endl;
						exit(1);
					}
					return num1 / num2;
		default:	cout << "The expression is not valid" <<endl;
					exit(1);
	}
}

void eval::Eval()
{
	char curr;
	Stack result;
	int num1,num2;
	string exp;

	cout << "Please enter expression: ";
	getline(cin, exp);
	//if empty string
	if(exp == "")
	{
		cout << "The expression is not valid"<<endl;
		exit(1);
	}


	InfixToPostfix(exp);
	m_num_stack.reverse();
	m_op_stack.reverse();

	while( !m_op_stack.isEmpty())
	{
		curr = m_op_stack.Pop();
		if( curr == '#')
			result.Push(m_num_stack.Pop());
		else
		{
			if(result.isEmpty())
			{
				cout << "The expression is not valid"<<endl;
				exit(1);
			}
			num2 = result.Pop();
			if(result.isEmpty())
			{
				cout << "The expression is not valid"<<endl;
				exit(1);
			}
			num1 = result.Pop();
			result.Push( Compute(curr,num2,num1) );
			while( !result.isEmpty() )
			{
				m_num_stack.Push( result.Pop() );
				m_op_stack.Push('#');
			}
		}
	}
	cout << "The value of the expression is: " << result.Pop() <<endl;
}



